package pruebaciudad.formas;

import pruebaciudad.interfaces.Desplazable;

/**
 * Esta clase representa un punto en el plano euclidiano, en el cual las 
 * coordenadas están representadas en pixels, es decir, como números enteros.
  */
public class Punto {
    /**
     * Este es el valor que se usa para comparar cuan cercano esta un número
     * a cero. <br>Sirve cuando queremos comparar igualdad entre dos double, por
     * ejemplo en lugar de usar:<pre>
     *        a == b</pre>podemos usar:<pre>
     *        (a - b) &lt DELTA</pre>
     */
    public static final double DELTA = 0.000000000000001;
    /**
     * Dado que los puntos son inmutables no tiene sentido generar mas de
     * un objeto que represente al origen
     */
    public static final Punto ORIGEN = new Punto(0, 0);
    private int x, y;
    
    /**
     * Constructor de un punto
     * 
     * @param x 
     * @param y 
     */
    public Punto(int x, int y){
        this.x = x;
        this.y = y;
    }
    
    /**
     * @return coordenada X del punto
     */
    public int getX(){
        return x;
    }
    
    /**
     * @return coordenada Y del punto
     */
    public int getY(){
        return y;
    }
    
    /**
     * Calcula la distancia entre dos puntos
     * 
     * @param p Punto a medir
     * @return distancia entre este punto y p
     */
    public double distanciaA(Punto p){
        double xx = x - p.x;
        double yy = y - p.y;
        return Math.sqrt(xx * xx + yy * yy);
    }
    
    /**
     * Calcula la distancia desde el origen hasta este punto
     * 
     * @return distancia entre este punto y el origen
     */
    public double distanciaAlOrigen(){
        return distanciaA(ORIGEN);
    }
    
    @Override
    public String toString(){
        return String.format("(%d, %d)", x, y);
    }
    
    @Override
    public boolean equals(Object obj){
        if (this == obj){
            return true;
        }
        
        if (obj instanceof Punto){
            Punto p = (Punto)obj;
            return x == p.x && y == p.y;
        }
        
        return false;
    }
    
    public static final int NINGUN_CUADRANTE  = 0;
    public static final int PRIMER_CUADRANTE  = 1;
    public static final int SEGUNDO_CUADRANTE = 2;
    public static final int TERCER_CUADRANTE  = 3;
    public static final int CUARTO_CUADRANTE  = 4;
    /**
     * Calcula en que cuadrante se encuentra el punto, y devuelve 
     * {@link Punto NINGUN_CUADRANTE} en caso de que el punto se encuentre en
     * el origen o sobre alguno de los ejes.
     * 
     * @return un int que representa al cuadrante
     * 
     * @see Punto NUNGUN_CUADRANTE
     * @see Punto PRIMER_CUADRANTE
     * @see Punto SEGUNDO_CUADRANTE
     * @see Punto TERCER_CUADRANTE
     * @see Punto CUARTO_CUADRANTE
     */
    public int getCuadrante(){
        if (x == 0 || y == 0){
            return NINGUN_CUADRANTE;
        }
        
        if (x > 0){
            if (y > 0){
                return PRIMER_CUADRANTE;
            } else {
                return CUARTO_CUADRANTE;
            }
        } else {
            if (y > 0){
                return SEGUNDO_CUADRANTE;
            } else {
                return TERCER_CUADRANTE;
            }
        }
    }

    @Override
    public int hashCode() {
        int hash = 5;
        hash = 59 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
        hash = 59 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
        return hash;
    }
}

